Add support for getting the xend log.
Needed response headers and mime-types in the xend client code.
Add command groups in xm help.
40c9c469TaZ83ypsrktmPSHLEZiP5w tools/python/xen/xend/server/SrvRoot.py
40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/python/xen/xend/server/SrvServer.py
40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/python/xen/xend/server/SrvVnetDir.py
+4108f181GtRoD1U9TBuJXMfBbGJwdQ tools/python/xen/xend/server/SrvXendLog.py
40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/python/xen/xend/server/__init__.py
40c9c4692hckPol_EK0EGB16ZyDsyQ tools/python/xen/xend/server/blkif.py
40c9c469N2-b3GqpLHHHPZykJPLVvA tools/python/xen/xend/server/channel.py
class XendClientProtocol:
"""Abstract class for xend clients.
"""
-
def xendRequest(self, url, method, args=None):
"""Make a request to xend.
Implement in a subclass.
"""Handle the data returned in response to the request.
"""
if data is None: return None
+ type = self.getHeader('Content-Type')
+ if type != sxp.mime_type:
+ return data
try:
pin = sxp.Parser()
pin.input(data);
"""
raise err
+ def getHeader(self, key):
+ """Get a header from the response.
+ Case is ignored in the key.
+
+ @param key: header key
+ @return: header
+ """
+ raise NotImplementedError()
+
class SynchXendClientProtocol(XendClientProtocol):
"""A synchronous xend client. This will make a request, wait for
the reply and return the result.
"""
+ resp = None
+
def xendRequest(self, url, method, args=None):
"""Make a request to xend.
if DEBUG: conn.set_debuglevel(1)
conn.request(method, url.fullpath(), self.request.data, self.request.headers)
resp = conn.getresponse()
+ self.resp = resp
val = self.handleStatus(resp.version, resp.status, resp.reason)
if val is None:
data = None
val = self.handleResponse(data)
return val
+ def getHeader(self, key):
+ return self.resp.getheader(key)
+
+
class AsynchXendClient(http.HTTPClient):
"""A subclass of twisted's HTTPClient to deal with a connection to xend.
Makes the request when connected, and delegates handling responses etc.
def handleStatus(self, version, status, message):
return self.protocol.handleStatus(version, status, message)
+ def handleHeader(self, key, val):
+ return self.protocol.handleHeader(key, val)
+
def handleResponse(self, data):
return self.protocol.handleResponse(data)
"""
def __init__(self):
self.err = None
+ self.headers = {}
def xendRequest(self, url, method, args=None):
"""Make a request to xend. The returned deferred is called when
the result is available.
-
+
@param url: xend request url
@param method: http method: POST or GET
@param args: request arguments (dict)
def handleException(self, err):
return self.callErrback(err)
- def handleResponse(self, data):
- if self.err: return self.err
- val = XendClientProtocol.handleResponse(self, data)
- if isinstance(val, Exception):
- self.callErrback(val)
- else:
- self.callCallback(val)
- return val
-
- def __init__(self):
- self.err = None
-
- def xendRequest(self, url, method, args=None):
- """Make a request to xend. The returned deferred is called when
- the result is available.
-
- @param url: xend request url
- @param method: http method: POST or GET
- @param args: request arguments (dict)
- @return: deferred
- """
- request = XendRequest(url, method, args)
- self.deferred = Deferred()
- clientCreator = ClientCreator(reactor, AsynchXendClient, self, request)
- clientCreator.connectTCP(url.host, url.port)
- return self.deferred
-
- def callErrback(self, err):
- if not self.deferred.called:
- self.err = err
- self.deferred.errback(err)
- return err
-
- def callCallback(self, val):
- if not self.deferred.called:
- self.deferred.callback(val)
- return val
+ def handleHeader(self, key, val):
+ self.headers[key.lower()] = val
- def handleException(self, err):
- return self.callErrback(err)
+ def getHeader(self, key):
+ return self.headers.get(key.lower())
def handleResponse(self, data):
if self.err: return self.err
def eventurl(self, id=''):
return self.url.relative('event/' + str(id))
- def dmesgurl(self, id=''):
- return self.url.relative('node/dmesg/' + str(id))
-
def xend(self):
return self.xendGet(self.url)
def xend_node_shutdown(self):
return self.xendPost(self.nodeurl(),
- {'op' : 'shutdown'})
+ {'op' : 'shutdown'})
def xend_node_restart(self):
return self.xendPost(self.nodeurl(),
- {'op' : 'reboot'})
+ {'op' : 'reboot'})
def xend_node_dmesg(self):
- return self.xendGet(self.dmesgurl())
+ return self.xendGet(self.nodeurl('dmesg'))
+
+ def xend_node_log(self):
+ return self.xendGet(self.nodeurl('log'))
def xend_node_cpu_rrobin_slice_set(self, slice):
return self.xendPost(self.nodeurl(),
-# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+ # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
"""Get dmesg output for this node.
"""
self.xc = xen.lowlevel.xc.new()
def info(self):
- return [ self.xc.readconsolering() ]
+ return self.xc.readconsolering()
def instance():
mode='a',
maxBytes=self.maxBytes,
backupCount=self.backupCount)
+ self.logfilename = filename
self.logfile.setFormatter(Formatter(self.logFileFormat, self.dateFormat))
log = self.getLogger()
log.addHandler(self.logfile)
def getLogFile(self):
return self.logfile
+ def getLogFilename(self):
+ return self.logfilename
+
def initLogStderr(self):
self.logstderr = StreamHandler()
self.logstderr.setFormatter(Formatter(self.logStderrFormat, self.dateFormat))
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
import os
-from SrvDir import SrvDir
+
from xen.xend import sxp
from xen.xend import XendDmesg
+from SrvDir import SrvDir
+
class SrvDmesg(SrvDir):
"""Xen Dmesg output.
"""
def render_GET(self, req):
try:
if self.use_sxp(req):
- req.setHeader("Content-Type", sxp.mime_type)
- sxp.show(['dmesg'] + self.info(), out=req)
+ req.setHeader("Content-Type", "text/plain")
+ req.write(self.info())
else:
req.write('<html><head></head><body>')
- req.write('<pre>')
self.print_path(req)
- req.write(self.info()[0])
+ req.write('<pre>')
+ req.write(self.info())
req.write('</pre></body></html>')
return ''
except Exception, ex:
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
import os
+
from SrvDir import SrvDir
from xen.xend import sxp
from xen.xend import XendNode
SrvDir.__init__(self)
self.xn = XendNode.instance()
self.add('dmesg', 'SrvDmesg')
+ self.add('log', 'SrvXendLog')
def op_shutdown(self, op, req):
val = self.xn.shutdown()
req.write('<ul>')
for d in self.info():
req.write('<li> %10s: %s' % (d[0], str(d[1])))
- req.write('<li><a href="' + url + 'dmesg">Xen dmesg output</a>')
+ req.write('<li><a href="%sdmesg">Xen dmesg output</a>' % url)
+ req.write('<li><a href="%slog>Xend log</a>' % url)
req.write('</ul>')
req.write('</body></html>')
return ''
--- /dev/null
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from twisted.web import static
+
+from xen.xend import XendRoot
+
+from SrvDir import SrvDir
+
+class SrvXendLog(SrvDir):
+ """Xend log.
+ """
+
+ def __init__(self):
+ SrvDir.__init__(self)
+ logging = XendRoot.instance().get_logging()
+ self.logfile = static.File(logging.getLogFilename(), defaultType="text/plain")
+ self.logfile.type = "text/plain"
+ self.logfile.encoding = None
+
+ def render_GET(self, req):
+ try:
+ return self.logfile.render(req)
+ except Exception, ex:
+ self._perform_err(ex, req)
from xen.xend.XendClient import main as xend_client_main
from xen.xm import create, destroy, shutdown
+class Group:
+
+ name = ""
+ info = ""
+
+ def __init__(self, xm):
+ self.xm = xm
+ self.progs = {}
+
+ def addprog(self, prog):
+ self.progs[prog.name] = prog
+
+ def getprog(self, name):
+ return self.progs.get(name)
+
+ def proglist(self):
+ kl = self.progs.keys()
+ kl.sort()
+ return [ self.getprog(k) for k in kl ]
+
+ def help(self, args):
+ if self.info:
+ print
+ print self.info
+ print
+ else:
+ print
+
+ def shortHelp(self, args):
+ self.help(args)
+ for p in self.proglist():
+ p.shortHelp(args)
+
class Prog:
"""Base class for sub-programs.
"""
self.name = 'xm'
self.unknown = ProgUnknown(self)
self.progs = {}
+ self.groups = {}
def err(self, msg):
print >>sys.stderr, "Error:", msg
"""
p = pklass(self)
self.progs[p.name] = p
+ self.getgroup(p.group).addprog(p)
return p
def getprog(self, name, val=None):
return self.progs.get(match, val)
- def proglist(self):
- """Get a list of sub-programs, ordered by group.
- """
- groups = {}
- for p in self.progs.values():
- l = groups.get(p.group, [])
- l.append(p)
- groups[p.group] = l
- kl = groups.keys()
+ def group(self, klass):
+ g = klass(self)
+ self.groups[g.name] = g
+ return g
+
+ def getgroup(self, name):
+ return self.groups[name]
+
+ def grouplist(self):
+ kl = self.groups.keys()
kl.sort()
- pl = []
- for k in kl:
- l = groups[k]
- l.sort()
- pl += l
- return pl
+ return [ self.getgroup(k) for k in kl ]
# Create the application object, then add the sub-program classes.
xm = Xm()
+class GroupAll(Group):
+
+ name = "all"
+ info = ""
+
+xm.group(GroupAll)
+
+class GroupDomain(Group):
+
+ name = "domain"
+ info = "Commands on domains:"
+
+xm.group(GroupDomain)
+
+class GroupScheduler(Group):
+
+ name = "scheduler"
+ info = "Comands controlling scheduling:"
+
+xm.group(GroupScheduler)
+
+class GroupHost(Group):
+
+ name = "host"
+ info = "Commands related to the xen host (node):"
+
+xm.group(GroupHost)
+
+class GroupConsole(Group):
+
+ name = "console"
+ info = "Commands related to consoles:"
+
+xm.group(GroupConsole)
+
class ProgHelp(Prog):
name = "help"
else:
print '%s: Unknown command: %s' % (self.name, name)
else:
- for p in self.xm.proglist():
- p.shortHelp(args)
+ for g in self.xm.grouplist():
+ g.shortHelp(args)
print "\nTry '%s help CMD' for help on CMD" % self.xm.name
main = help
class ProgList(Prog):
group = 'domain'
name = "list"
- info = """List info about domains."""
+ info = """List information about domains."""
short_options = 'l'
long_options = ['long']
info = """Open a console to a domain."""
def help(self, args):
- print "console DOM"
+ print args[0], "DOM"
print "\nOpen a console to domain DOM."
def main(self, args):
info = "Call xend api functions."
def help (self, args):
- print "call fn argss..."
+ print args[0], "function args..."
print """
Call a xend HTTP API function. The leading 'xend_' on the function
can be omitted. See xen.xend.XendClient for the API functions.
info = """Print Xen boot output."""
def main(self, args):
- print server.xend_node_dmesg()[1]
+ print server.xend_node_dmesg()
xm.prog(ProgDmesg)
+class ProgLog(Prog):
+ group = 'host'
+ name = "log"
+ info = """Print the xend log."""
+
+ def main(self, args):
+ print server.xend_node_log()
+
+xm.prog(ProgLog)
+
def main(args):
xm.main(args)
from xen.xend.XendClient import server
from xen.xm.opts import *
-DOM0 = 'Domain-0'
+DOM0_NAME = 'Domain-0'
+DOM0_ID = '0'
gopts = Opts(use="""[options] [DOM]
def shutdown(opts, doms, mode, wait):
if doms == None: doms = server.xend_domains()
- if DOM0 in doms:
- doms.remove(DOM0)
+ for x in [DOM0_NAME, DOM0_ID]:
+ if x in doms:
+ doms.remove(x)
for d in doms:
server.xend_domain_shutdown(d, mode)
if wait: